package com.zj.service.aop;

import com.zj.service.User;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Component //将切面类声明为一个bean
@Aspect //声明这是一个切面类
@Order(-2)
public class LogAnnotationAspect {


    private ThreadLocal<Map<String, Long>> methodcost = new ThreadLocal<Map<String, Long>>() {
        @Override
        protected Map<String, Long> initialValue() {
            return new HashMap<>(); // 设置默认值为 0
        }
    };

    @Pointcut("execution(* com.zj.service.UserService.*(..))")
    public void pointcut1() {
    }
    @Pointcut("execution(* com.zj.service.UserService.*(..))&& args(user)")
    public void pointcut2(User user) {
    }

    @Pointcut("execution(* com.zj.service.UserService.*(..))&& @args(com.zj.service.aop.MyDes)")
    //在切点表达式中@args表示方法参数上必须有Description注解修饰,属于切点条件之一
    public void pointcut3() {
    }

//    @Around("pointcut1()")
//    @Order(-2)
//    public Object logAdd(ProceedingJoinPoint pj) {
//        long now = System.currentTimeMillis();
//
//        //前置通知部
//        System.out.println("start: " + now + " function:" + pj.getSignature() + " args:" + Arrays.toString(pj.getArgs()));
//        Object proceed = null;
//        try {
//            proceed = pj.proceed();
//
//        } catch (Throwable e) {
//            //异常通知部分
//            System.out.println("exception = " + e.getMessage());
//        } finally {
//            //后置通知也叫最终通知部分
//            long end = System.currentTimeMillis();
//            System.out.println("finally end:" + end + ", cost: " + (end - now));
//        }
//        return proceed;
//    }

    @Before("pointcut2(user)")
    //before要想获取方法参数，需要在切点表达式中给出参数&& args(user)，且在切点方法pointcut中加上形参User
    public void Before(JoinPoint pj,User user) {
        Map<String, Long> threadMap = methodcost.get();
        long start = System.currentTimeMillis();
        threadMap.put(pj.getSignature().toShortString() + Thread.currentThread().getId(), System.currentTimeMillis());
        System.out.println("Before:" + pj.getSignature() + ", " + start);
    }


    @Before("pointcut1()")
    public void ABefore2(JoinPoint pj) {
        long start = System.currentTimeMillis();
        System.out.println("Before2:" + pj.getSignature() + ", " + start);
    }

    @After("pointcut2(user)")
    public void After(JoinPoint pj,User user) {
        Map<String, Long> threadMap = methodcost.get();
        long end = System.currentTimeMillis();
        long cost = end - threadMap.get(pj.getSignature().toShortString() + Thread.currentThread().getId());
        System.out.println("After: " + pj.getSignature() + ",end:" + end + ", costtime:" + cost);
    }

    @AfterReturning("pointcut1()")
    public void AfterReturning(JoinPoint pj) {
        long end = System.currentTimeMillis();
        System.out.println("AfterReturning: " + pj.getSignature() + ",end:" + end );
    }


}
